package cn.dxh.stagefinal.utils;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * IntelliJ IDEA -> MyPersonSSMDemo
 * 2019/11/22 19:53
 *
 * @author Wenhao Lee
 * 高山仰止,景行行止.虽不能至,心向往之。
 */
public class ExcelUtils<T> {
    private static HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
    private static HSSFSheet hssfSheet = hssfWorkbook.createSheet("sheet1");

    public void export(List<T> data, OutputStream outputStream) throws IOException {
        Map<String, Object> headMap = toMap(data.get(0));
        List<String> heads = new LinkedList<>(headMap.keySet());
        HSSFRow row = hssfSheet.createRow(0);
        for (int i = 0; i < heads.size(); i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellValue(heads.get(i));
        }
        for (int i = 0; i < data.size(); i++) {
            HSSFRow hssfRow = hssfSheet.createRow(i + 1);
            Map<String, Object> map = toMap(data.get(i));
            AtomicReference<Integer> index = new AtomicReference<>(0);
            map.forEach((k, v) -> {
                HSSFCell cell = hssfRow.createCell(index.get());
                StringBuilder sb = new StringBuilder();
                //如果map某个key的值 是list 则遍历后加到stringBuilder中
                if (v instanceof List) {
                    ((List<?>) v).forEach(sb::append);
                    v = sb.toString();
                }
                cell.setCellValue(String.valueOf(v));
                index.set(index.get() + 1);
            });
        }
        hssfSheet.setGridsPrinted(true);
        hssfWorkbook.write(outputStream);
    }

    /**
     * 将对象转换为Map集合
     *
     * @param t 需要转换的实体类
     * @return 生成的map集合
     */
    private Map<String, Object> toMap(T t) {
        Map<String, Object> map = new LinkedHashMap<>();
        Class<?> cls = t.getClass();
        for (Field field : cls.getDeclaredFields()) {
            field.setAccessible(true);
            String fieldName = field.getName();
            Object fieldValue = null;
            try {
                fieldValue = field.get(t);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            map.put(fieldName, fieldValue);
        }
        return map;
    }
}
